package com.boarsoft.dao.sharding.oceanbase.filter;

import java.sql.SQLException;
import java.util.List;

import com.alibaba.druid.filter.FilterAdapter;
import com.alibaba.druid.filter.FilterChain;
import com.alibaba.druid.proxy.jdbc.ConnectionProxy;
import com.alibaba.druid.proxy.jdbc.PreparedStatementProxy;
import com.boarsoft.dao.sharding.bean.ShardingParam;
import com.boarsoft.dao.sharding.datasource.DynamicDataSource;
import com.boarsoft.dao.sharding.oceanbase.mybatis.inspector.RouteCondition;
import com.boarsoft.dao.sharding.oceanbase.mybatis.inspector.RouteParameters;

import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.util.TablesNamesFinder;

/**
 * 实现DRUID filter：拦截prepareStatement的构建，以修改SQL，为SQL添加hint
 */
public class DruidShardingFilter extends FilterAdapter {

	@Override
	public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql)
			throws SQLException {
		try {
			return super.connection_prepareStatement(chain, connection, getRouteSql(sql));
		} catch (JSQLParserException e) {
			throw new SQLException(e);
		}
	}

	@Override
	public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql,
			int autoGeneratedKeys) throws SQLException {
		try {
			return super.connection_prepareStatement(chain, connection, getRouteSql(sql), autoGeneratedKeys);
		} catch (JSQLParserException e) {
			throw new SQLException(e);
		}
	}

	/**
	 * 修改SQL，为SQL添加hint
	 * 
	 * @param processSql
	 * @return
	 * @throws JSQLParserException
	 */
	public String getRouteSql(String processSql) throws JSQLParserException {
		ShardingParam sp = DynamicDataSource.getBinding();
		if (sp == null) {
			return processSql;
		}
		RouteParameters rp = RouteCondition.getRouteParameters();
		String uid = (String) sp.getKey();
		if (rp != null) {
			return new StringBuilder().append("/*+DBP:$ROUTE={GROUP_ID(").append(rp.getGroupId())//
					.append("),TABLE_NAME(").append(calTableName(processSql)).append("_").append(uid)//
					.append(")}*/").append(processSql).toString();
		}
		return new StringBuilder().append("/*+DBP:$ROUTE={GROUP_ID(").append(uid)//
				.append("),TABLE_NAME(").append(calTableName(processSql)).append("_")//
				.append(uid).append(")}*/").append(processSql).toString();
	}

	/**
	 * 获取表名，并修改（目前只支持单表）
	 * 
	 * @param processSql
	 * @return
	 * @throws JSQLParserException
	 */
	private String calTableName(String processSql) throws JSQLParserException {
		Statement statement = CCJSqlParserUtil.parse(processSql);
		TablesNamesFinder tablesNamesFinder = new TablesNamesFinder();
		List<String> tableList = tablesNamesFinder.getTableList(statement);
		return tableList.get(0);
	}
}